using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Volo.Abp;
using Volo.Abp.Localization;

namespace Jy.Abp.Authorization;

public static class PermissionHelper
{
    private static readonly List<Assembly> _regedAssemblies = new List<Assembly>();

    /// <summary>
    /// 权限分组类型(class)
    /// </summary>
    public static List<Type> GroupTypes = new List<Type>();

    public static IDictionary<string, PermissionGroupAttribute> Groups = new Dictionary<string, PermissionGroupAttribute>();
    /// <summary>
    /// 权限定义,key为类型或者类型的全名
    /// </summary>
    public static IDictionary<string, PermissionAttribute> PermissionDefines = new Dictionary<string, PermissionAttribute>();

    private static string RemovePostFix(string name)
    {

        return name.RemovePostFix("Permissions")
            .RemovePostFix("Permission");
    }

    private static string GetDisplayKey(string key) 
    {
        return $"{PermissionAttribute.LocalizablePrev}{key}";
    }

    public static PermissionGroupAttribute GetGroup(Type type)
    {
        var defineName = type.FullName;
        if (!Groups.ContainsKey(defineName))
        {
            var group = type.GetCustomAttribute<PermissionGroupAttribute>(false)
                     ?? new PermissionGroupAttribute();
            var groupName = group.Name ?? RemovePostFix(type.Name);
            group.DeclaringType = type;
            group.Name = groupName;
            group.DisplayNameKey = group.DisplayNameKey ?? GetDisplayKey(groupName);
            Groups.Add(defineName, group);
        }
        return Groups[defineName];
    }

    /// <summary>
    /// 获取类型的权限信息
    /// </summary>
    public static PermissionAttribute GetDefine(Type type)
    {
        if (!type.IsEnum)
            throw new UserFriendlyException($"{type}非枚举类型！");
        var defineName = type.FullName;
        if (!PermissionDefines.ContainsKey(defineName))
        {
            var group = GetGroup(type.DeclaringType);
            var permission = type.GetCustomAttribute<PermissionAttribute>(false)
                          ?? new PermissionAttribute();
            var permissionName = permission.Name ?? RemovePostFix(type.Name);
            permission.DeclaringType = type;
            permission.Name = $"{group.Name}.{permissionName}";
            permission.DisplayNameKey = permission.DisplayNameKey ?? GetDisplayKey(permissionName);
            PermissionDefines[defineName] = permission;
        }
        return PermissionDefines[defineName];
    }
    /// <summary>
    /// 获取字段的权限信息
    /// </summary>
    public static PermissionAttribute GetDefine(FieldInfo field)
    {
        var parentType = field.DeclaringType;
        var defineName = $"{parentType}.{field.Name}";

        if (!PermissionDefines.ContainsKey(defineName))
        {
            var parent = GetDefine(parentType);
            var permission = field.GetCustomAttribute<PermissionAttribute>(false)
                          ?? new PermissionAttribute();
            var permissionName = permission.Name ?? field.Name;
            permission.DeclaringType = parentType;
            permission.Name = $"{parent.Name}.{permissionName}";
            permission.DisplayNameKey = permission.DisplayNameKey ?? GetDisplayKey(permissionName);
            PermissionDefines[defineName] = permission;
        }
        return PermissionDefines[defineName];
    }

    /// <summary>
    /// 获取显示名称
    /// </summary>
    public static ILocalizableString GetDisplayName(Type resourceType, string permissionName) =>
        LocalizableString.Create(resourceType, $"{PermissionAttribute.LocalizablePrev}{permissionName}");

    /// <summary>
    /// 获取指定权限名称的权限定义
    /// </summary>
    public static PermissionAttribute GetDefine(string permissionName)
    {
        var item = PermissionDefines.FirstOrDefault(t => t.Value.Name == permissionName);
        if (item.Value != null)
            return item.Value;
        throw new UserFriendlyException($"{permissionName}未定义。");
    }
    /// <summary>
    /// 获取枚举类型的权限名
    /// </summary>
    public static string GetPermissionName<TEnum>()
        where TEnum : Enum
    {
        return GetDefine(typeof(TEnum)).Name;
    }
    /// <summary>
    /// 获取指定对像的权限名称,只支持字符串及枚举
    /// </summary>
    public static string GetPermissionName(object val)
    {
        if (val is string)
            return val?.ToString();
        if (val is Enum @enum)
        {
            var cInfo = GetDefine(@enum.GetType().GetField(val.ToString()));
            return cInfo.Name;
        }
        throw new UserFriendlyException($"不支持的权限：{val}");
    }
    /// <summary>
    /// 把多个权限组合成一个权限组合名
    /// </summary>
    public static string GetCombination(params object[] permissions)
    {
        var ps = permissions.Select(t => GetPermissionName(t));
        return string.Join("|", ps);
    }
    /// <summary>
    /// 把权限组合名拆分成多个权限名
    /// </summary>
    public static string[] GetFromCombination(string permissionCombine)
    {
        return permissionCombine.Split('|');
    }


    /// <summary>
    /// 注册程序集中的所有定义的权限类
    /// </summary>
    public static void RegisterEnumPermissionTypes(params Assembly[] assemblies)
    {
        if (assemblies.IsNullOrEmpty())
            return;
        foreach (var assembly in assemblies)
        {
            if (_regedAssemblies.Any(t => t.FullName == assembly.FullName))
                return;
            _regedAssemblies.Add(assembly);
            var types = assembly.GetTypes()
              .Where(t => t.IsDefined(typeof(PermissionGroupAttribute)));
            GroupTypes.AddRange(types);
        }
    }
}

